﻿// ******************************************************************
// 项目名称 :WSPay
// 项目描述 :
// 文件名称 : RefoundService.cs
// 版  本 : v1.0.0.0
// 说  明 :  
// 作  者 : mengzhong
// 邮  箱 :coodream@live.com
// 命名空间 : WSPay.Core
// 创建时间 : 2017.04.21.11:32
// 更新时间 : 2017.04.21.11:32
// ******************************************************************
//  Copyright meng zhong  2017. All rights reserved.
// ******************************************************************

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Transactions;
using Hangfire;
using WSPay.Common;
using WSPay.Common.Data;
using WSPay.Common.Log;
using WSPay.Core.DTO;
using WSPay.Domain;

namespace WSPay.Application
{
    public class RefoundService:BaseService,IRefoundService
    {
      
        public RefoundService(IUnitOfWork unitOfWork) : base(unitOfWork)
        {
          
        }

        public RefundOrder CreateRefundOrder(RefundOrderDto dto)
        {
            if (ValidateSignRefound(dto) != true)
            {
                return null;
            }
            using (TransactionScope scope = new TransactionScope())
            {
                var payorder =
                    _unitOfWork.D<PaymentOrder>().ReadQuery().FirstOrDefault(x => x.BuyOrderId == dto.BuyOrderId);
                var refound = new RefundOrder()
                {
                    PaymentOrderId = payorder.OrderId,
                    NoticeSn = payorder.NoticeSn,
                    UserID = payorder.UserID,
                    State = RefundState.Wait,
                    Amount = payorder.PayAmount,
                    Remark = "支付退款：" + payorder.Remark,
                    CreateTime = DateTime.Now,
                    UpdateTime = DateTime.Now,
                    ClientID = dto.ClientID.ToString(),
                    RuturnUrl=dto.RuturnUrl,
                    NoticeUrl = dto.NoticeUrl,
                    BatchNo = DateTime.Now.ToString("yyyyMMdd")+"".RandomNo(),
                };
                _unitOfWork.D<RefundOrder>().Insert(refound);
                _unitOfWork.Commit();
                scope.Complete();
                return refound;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="reamak"></param>
        /// <returns></returns>
        public bool SuccessRefound(int orderId, string reamak)
        {
            var data = _unitOfWork.D<RefundOrder>().GetById(orderId);
            data.State = RefundState.Completed;
            data.Remark += reamak;
            var jobId = BackgroundJob.Schedule(
          () => Notice(data.OrderId), TimeSpan.FromMilliseconds(10));
            data.JobId = jobId;
            _unitOfWork.Commit();
            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="orderId"></param>
        /// <param name="reamak"></param>
        /// <returns></returns>
        public bool FailureRefound(int orderId, string reamak)
        {
            var data = _unitOfWork.D<RefundOrder>().GetById(orderId);
            data.State = RefundState.Failure;
            data.Remark += reamak;
            var jobId = BackgroundJob.Schedule(
            () => Notice(data.OrderId), TimeSpan.FromMilliseconds(10));
            data.JobId = jobId;
            _unitOfWork.Commit();
            return true;
        }
        /// <summary>
        /// 退款通知
        /// </summary>
        /// <param name="orderId"></param>
        public void Notice(string orderId)
        {
            try
            {
                var _httpClient = new HttpClient();
                var data = _unitOfWork.D<RefundOrder>().Query().FirstOrDefault(x => x.OrderId == orderId);
                var clientInfo = _unitOfWork.Q<ClientInfo>().FirstOrDefault(x => x.Guid == Guid.Parse(data.ClientID));
                var paymentOrder= _unitOfWork.D<PaymentOrder>().Query().FirstOrDefault(x => x.OrderId == data.PaymentOrderId);
                if (clientInfo == null)
                {
                    throw new ApplicationException("ClientID is null");
                }

                var sp = "|";

                var signString = data.ClientID + sp +
                                 clientInfo.MD5Key + sp +
                                 paymentOrder.BuyOrderId + sp +
                                 data.OrderId + sp +
                                 data.State + sp +
                                 paymentOrder.PayAmount.ToString("0") + sp +
                                 data.UserID + sp;
                var sign = signString.Hash();
                _httpClient.BaseAddress = new Uri(data.NoticeUrl);
                var content = new FormUrlEncodedContent(new Dictionary<string, string>()
                   {
                       {"OrderId", data.OrderId},
                       {"PayerID", data.UserID.ToString()},
                       {"BuyOrderId", data.UserID.ToString()},
                       {"ClientID", data.ClientID},
                       {"State", data.State.ToString()},
                       {"OrderMoney",paymentOrder.PayAmount.ToString("0")},
                       {"Sign", sign}

                   });
                NLogLogger nlog = new NLogLogger();
                var response = _httpClient.PostAsync(data.NoticeUrl, content);
                string responseString = response.Result.Content.ReadAsStringAsync().Result;
                nlog.Info(responseString);
                if (responseString != "success")//不成功继续通知
                {
                    BackgroundJob.Schedule(
                         () => Notice(data.OrderId), TimeSpan.FromMilliseconds(10));
                }
            }
            catch (Exception e)
            {
                throw new ApplicationException(e.Message);
            }
        }

        public RefundOrder GetRefundOrderByBath(string bathId)
        {
            return _unitOfWork.D<RefundOrder>().ReadQuery().FirstOrDefault(x => x.BatchNo == bathId);
        }

        public RefundOrder GetRefundOrder(string paymentOrderId)
        {
            return _unitOfWork.D<RefundOrder>().ReadQuery().FirstOrDefault(x => x.PaymentOrderId == paymentOrderId);
        }
        private bool ValidateSignRefound(RefundOrderDto dto)
        {

            var clientInfo = _unitOfWork.Q<ClientInfo>().FirstOrDefault(x => x.Guid == dto.ClientID);

            if (clientInfo == null) return false;

            var sp = "|";

            var signString = dto.ClientID + sp +
                clientInfo.MD5Key + sp +
                dto.BuyOrderId + sp +
                dto.RuturnUrl + sp +
                dto.NoticeUrl + sp +
                dto.TradeDate.ToString("yyyy-MM-dd HH:mm:ss") + sp +
                dto.Remark;

            var sign = signString.Hash();

            if (string.IsNullOrEmpty(dto.Sign) || !dto.Sign.ToUpper().Equals(sign))
            {
                return false;
            }

            return true;
        }
        /// <summary>
        /// 退款通知
        /// </summary>
        /// <param name="orderId"></param>
        public void NoticeRefund(string orderId)
        {
           var  _httpClient = new HttpClient();
            try
            {
                var data = _unitOfWork.D<RefundOrder>().Query().FirstOrDefault(x => x.PaymentOrderId == orderId);
                var clientInfo = _unitOfWork.Q<ClientInfo>().FirstOrDefault(x => x.Guid == Guid.Parse(data.ClientID));
                var payorder = _unitOfWork.D<PaymentOrder>().Query().FirstOrDefault(x => x.OrderId == orderId);
                if (clientInfo == null)
                {
                    throw new ApplicationException("ClientID is null");
                }

                var sp = "|";

                var signString = data.ClientID + sp +
                                 clientInfo.MD5Key + sp +
                                 payorder.BuyOrderId + sp +
                                 data.OrderId + sp +
                                 data.State + sp +
                                 payorder.PayAmount.ToString("0") + sp +
                                 data.UserID + sp;

                var sign = signString.Hash();
                _httpClient.BaseAddress = new Uri(data.NoticeUrl);
                var content = new FormUrlEncodedContent(new Dictionary<string, string>()
                   {
                       {"OrderId", data.OrderId},
                       {"PayerID", data.UserID.ToString()},
                       {"BuyOrderId", payorder.BuyOrderId},
                       {"State", data.State.ToString()},
                       {"ClientID", data.ClientID},
                       {"OrderMoney",payorder.PayAmount.ToString("0")},
                       {"Sign", sign}
                   });
                var response = _httpClient.PostAsync(data.NoticeUrl, content);
                string responseString = response.Result.Content.ReadAsStringAsync().Result;
                if (responseString != "SUCCESS")//不成功继续通知
                {
                    BackgroundJob.Schedule(
                         () => NoticeRefund(data.OrderId), TimeSpan.FromMilliseconds(10));
                }
            }
            catch (Exception e)
            {
                throw new ApplicationException(e.Message);
            }
        }
    }
}